package typinggame;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.awt.*;
import java.awt.event.KeyEvent;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;



/**
 *
 * @author suhui
 */
public class gameplayview extends Canvas implements Runnable{
    private static final int DEFAULT_WIDTH = 750;	// default parameters
    private static final int DEFAULT_HEIGHT = 500;
    private static final int INITIAL_DELAY = 5000;
    private static final int startframe = 0;
    private static final int endframe = 9;
    private static final int std_DELAY = 10;
    private static final int defaultstart = 130;
    private static final int defaultenemystart = 100;
    private static final Color DEFAULT_GAME_COLOR = Color.white;
    private static final Font DEFAULT_GAME_FONT = new Font("TimesRoman", Font.PLAIN, 12);

    GameInfo thisgame;

    private int width, height, delay, winwidth;				// actual parameters
    private Color gameColor;
    private Font gameFont;

    private int dlay = 50;

    private Thread animatorThread;
    public Vector <runningword> flyingwords = new Vector<runningword>();
     public Vector <runningword> enemywords = new Vector<runningword>();

    private Image offimage;

    private int frameno;

    private int fontHeight;

    private String attackbyp = "";
    private String defendbyp = "";

    runningword prevenemyattack;
    private String status = "Welcome to Invasion of the Alphabets: Hit Spacebar to Pause";
    
    private boolean CAPS;

    
    private int posx, posy,cursory, previouscursor;

    private boolean paused = false;

    private FontMetrics metrics;
    
    Hashtable msg_hashed = new Hashtable();
    //constructors
    public gameplayview(int width, int height, int delay,
			Color gameColor,
			Font gameFont){

        super();
        setSize(1000,height);
        this.width = width;
        this.winwidth = 1000;
        this.height = height;
        this.delay = delay;
        this.gameColor = gameColor;
        this.gameFont = gameFont;


        CAPS = Toolkit.getDefaultToolkit().getLockingKeyState(KeyEvent.VK_CAPS_LOCK);


        metrics = getFontMetrics(gameFont);
        fontHeight = metrics.getHeight();
        //fontWidth = metrics.

        cursory = 20;
        posx =10;
        posy = 10;
        animatorThread = null;
    }
    public gameplayview(int width, int height, int delay) {
		this(width, height, delay, DEFAULT_GAME_COLOR, DEFAULT_GAME_FONT);
	}
    public gameplayview() {
		this(DEFAULT_WIDTH, DEFAULT_HEIGHT,std_DELAY,DEFAULT_GAME_COLOR, DEFAULT_GAME_FONT);
	}
    //gets and sets
    public int getDelay() {
            return delay;
    }
    public boolean isActive() {
            return(animatorThread != null);
    }
    public void setDelay(int delay) {
            this.delay = delay;
    }

    //adding attacking string
    public void addattack(String word , boolean byme , int speed, int row)
    {
            int cursor = rowtocoord(row);
            //12 is a number for positioning purposes.
            posy = cursor + 12;
            runningword attack  = new runningword(word,defaultstart ,posy,"right",byme,speed);
            flyingwords.add(attack);

  
    }
    //other team's attack
    public void addenemyattack(String word , int row,int speed)
    {
            int posy_e = rowtocoord(row);
            //12 is a number for positioning purposes.
            posy_e += 12;
            runningword enemy  = new runningword(word, width-metrics.stringWidth(word) ,posy_e,"left",false,speed);
            enemywords.add(enemy);


    }
    //my own defense
    public boolean defendself(String word)
    {
        if (enemywords.isEmpty())
                return false;
        String firstenemyword = enemywords.firstElement().letters;
        if(firstenemyword.equals(word))
        {
            prevenemyattack = enemywords.firstElement();
            prevenemyattack.setintercepted();
            thisgame.interceptpts(firstenemyword.length(), prevenemyattack.getlevel());
            enemywords.removeElementAt(0);
            return true;
        }
        else
            return false;
    }

    //check opposition defense
    public boolean checkDefenderWord(String word)
    {
        String firstattack = flyingwords.firstElement().letters;

        if(firstattack.equals(word))
        {
            flyingwords.removeElementAt(0);
            return true;
        }
        else
            return false;
    }
    
    //animation thread stuff
    public void start(){
        stop();

        flyingwords.removeAllElements();
        
        
        animatorThread = new Thread(this);
        animatorThread.start();
    }
    public void stop() {
            if(animatorThread == null)
                    return;

            animatorThread.stop();
            animatorThread = null;
            
            repaint();
    }
    public void suspend() {
            if((animatorThread == null) )
                    return;

            animatorThread.suspend();
            paused = true;
            repaint();
    }
    public void resume() {
            if((animatorThread == null) || !paused)
                    return;

            animatorThread.resume();
            paused = false;
            repaint();
    }

    //graphics
    public void paint(Graphics g) {
        
            update(g);
    }
    public void update(Graphics g){

        if(animatorThread == null)
        {
            g.setColor(gameColor);
            g.drawString("DEATH", width/2, height/2);
            return;
        }
        if(paused)
        {
            g.setColor(gameColor);
            g.drawString("Paused - Press Spacebar to resume", width/2, height/2);
            return;
        }
        runningword thisword;
        //use another image to reduce flickering, update when all done
        Graphics offGraphics;
        offimage = createImage(winwidth, height);
        offGraphics = offimage.getGraphics();
        
        offGraphics.setColor(Color.GREEN);
        offGraphics.setFont(new Font("sansserif", Font.BOLD, 12));
        offGraphics.drawString(status, (width-metrics.stringWidth(status))/2, 10);

        //cursor
        offGraphics.setColor(Color.darkGray);
        if(CAPS)
        {
            offGraphics.fillRect(0, 460, width, 40);
            offGraphics.setColor(Color.red);
            offGraphics.drawString("DEFENDING", 15, 480);
        }
        else
        {
            offGraphics.fillRect(0, cursory, width, fontHeight);
            offGraphics.setColor(Color.red);
            offGraphics.drawString("ATTACKING", 15, 480);
        }
        
        //draw starting line
        //offGraphics.setColor(Color.red);
        offGraphics.setFont(new Font("TimesRoman", Font.BOLD, 12));
        offGraphics.drawLine(defaultstart, 0, defaultstart, height);

        //draw defending box
        offGraphics.drawRect(0, 460 , width-2, 39);
        offGraphics.drawString("Defend", 380, 470);
        
        //enemyline
        offGraphics.setColor(Color.blue);
        offGraphics.drawLine(width, 0, width, height);
        offGraphics.drawString("Enemy Base", width +10 , 250);
        //game info
        offGraphics.setColor(Color.gray);
        offGraphics.drawRoundRect(840, 5, 150, 300, 10, 10);

        offGraphics.drawString("Player: " + thisgame.getplayer(), 850, 20);
        offGraphics.drawString("Level: " + thisgame.getplayerlevel(), 850, 40);
        offGraphics.drawString("Max Word Size: " + thisgame.maxwordsize, 850, 60);
        offGraphics.drawString("Total Points: " +thisgame.expgained, 850, 80);
        //offGraphics.drawString("Character Fired: "+ thisgame.words_fired, 850, 100);
        offGraphics.drawString("Personal Hits: " + thisgame.hits, 850, 120);
        offGraphics.drawString("Team Hits: "+ thisgame.teamhits, 850, 140);
        offGraphics.drawString("Damage: " +thisgame.damage, 850, 160);
        offGraphics.drawString("Intercepted: " +thisgame.intercepted, 850, 180);
        offGraphics.drawString("Time Left: ", 850, 200);


        offGraphics.drawRoundRect(840, 310, 150, 180, 10, 10);
        offGraphics.drawString("Hit: +2 per char", 850, 365);
        offGraphics.drawString("Team Hit: +1 per char", 850, 380);
        offGraphics.drawString("Damage: -1 per char", 850, 395);
        offGraphics.drawString("Intercept: +1 per level per char", 850, 395);

        offGraphics.setFont(new Font("TimesRoman", Font.BOLD, 12));
        offGraphics.drawString("Invasion of the Alphabets", 845, 325);
        offGraphics.setFont(new Font("TimesRoman", Font.ITALIC, 12));
        offGraphics.drawString("Score Table", 850, 345);
        offGraphics.drawLine(850, 347, 912, 347);
        

        //draw words
        offGraphics.setColor(Color.white);
        //first input typing
        offGraphics.drawString(attackbyp, 5, cursory + 12);
        offGraphics.drawString(defendbyp, (width- metrics.stringWidth(defendbyp))/2+20, 470 + 12);
        //then draw words that are done
        thisword = null;

        for(int i = 0; i<flyingwords.size(); i++)
        {
            thisword = flyingwords.get(i);
            thisword.movew();

            if(thisword.byteam)
                offGraphics.setColor(Color.white);
            else
                offGraphics.setColor(Color.yellow);
            offGraphics.drawString(thisword.letters, thisword.x, thisword.y);
            
        }
        if(!flyingwords.isEmpty() && checkifhit())
        {
            //thisgame.update(thisword.letters.length(),0,0,0);
            flyingwords.remove(0);
            return;
        }
        offGraphics.setColor(Color.CYAN);
        for(int i = 0; i<enemywords.size(); i++)
        {

            thisword = enemywords.get(i);
            if(i>0 && enemywords.get(i-1).row == thisword.row)
            {
                if (thisword.x>enemywords.get(i-1).x+metrics.stringWidth(enemywords.get(i-1).letters)+5)
                    thisword.movew();
            }
            else
            thisword.movew();
            offGraphics.drawString(thisword.letters, thisword.x, thisword.y);

        }

        if(!enemywords.isEmpty() && checkifdamage())
        {
            thisgame.update(0,thisword.letters.length(),0, enemywords.firstElement().getlevel());
            prevenemyattack = enemywords.firstElement();
            enemywords.remove(0);
            return;
        }
        offGraphics.drawImage(offimage, 0, 0, this);

        g.drawImage(offimage, 0, 0, this);
    }

    public boolean checkifhit() //did my attack/teamattack hit
    {
        
        runningword firstword = flyingwords.firstElement();
        if((firstword.x + metrics.stringWidth(firstword.letters))>= width)
        {
            if(firstword.byteam)
                thisgame.update(0, 0, firstword.letters.length(), 0);
            else
                thisgame.update(firstword.letters.length(),0,0,0);
            return true;
        }
         else
            return false;

    }
    public boolean checkifdamage() //did enemy attack hit
    {

        runningword firstword = enemywords.firstElement();
        if(firstword.x <= defaultstart)
        {

            return true;
        }
        else
            return false;

    }
    //main run method
    public void run() {

        int i=0;
        while(Thread.currentThread() == animatorThread)
        {
            //testing functions
            i++;
            if(i==100)
                addenemyattack("wahahah" , 22,1);
            if(i==102)
                addenemyattack("beepboop" , 22,1);
            repaint();
        try {
            Thread.sleep(delay);
        } catch (InterruptedException ex) {
            Logger.getLogger(gameplayview.class.getName()).log(Level.SEVERE, null, ex);
        }
        }
    }
    //key press
    @Override
    public boolean keyDown(Event e, int key) {

		//If stopped, do nothing

		if(animatorThread == null)
			return true;

                switch(key)
                {
                    case Event.UP: cursory -= 40;
                                    if(cursory<=20)
                                        cursory=20;
                        break;
                    case Event.DOWN: cursory += 40;
                                    if(cursory>=420)
                                        cursory=420;
                        break;
                    case Event.CAPS_LOCK:
                                    CAPS =!CAPS;
                    case Event.ENTER: //case where Player has attacked
                        if(CAPS)
                        {
                            defendself(defendbyp);
                            cleardstr();
                        }
                        else
                        {
                            //attack only if string not empty and on different lane
                            if( !attackbyp.equals("")&& cursory != previouscursor)
                            {
                                //update previous cursor value
                                previouscursor = cursory;
                                
                                addattack(attackbyp,true, thisgame.getplayerlevel(),coordtorow(cursory));
                                
                                clearastr();
                            }
                            else if(cursory==previouscursor)
                                status = "Attack on a different Lane!";
                        }
                        break;
                    case Event.BACK_SPACE:
                        if(CAPS)
                        {
                            if(defendbyp.length()!=0)
                            defendbyp = defendbyp.substring(0, defendbyp.length()-1);

                        }
                        else
                            if(attackbyp.length()!=0)
                            attackbyp = attackbyp.substring(0, attackbyp.length()-1);

                        break;

                    default:
                        if((char)key==' ')
                            if(!paused)
                                suspend();
                            else
                                resume();
                        break;
                }
                System.out.println(cursory);
                //If it's not a ASCII character or is not printable, do nothing
                if((key <= 32) || (key >= 123))
			return true;
                else
                {
                    if(key>=97)
                    {
                        CAPS = false;
                        cleardstr();
                        if (attackbyp.length() < thisgame.maxwordsize)
                        attackbyp = attackbyp + (char)key;
                    }
                    else
                        if(key<=90)
                        {
                            CAPS=true;
                            clearastr();
                            defendbyp = defendbyp + (char)key;
                            defendbyp = defendbyp.toLowerCase();
                        }

                }
                    //System.out.println(attackbyp);

                return true;
    }
    private void clearastr()
    {
        attackbyp = "";
    }
    private void cleardstr()
    {
        defendbyp = "";
    }

    void setgameinfo(GameInfo info) {
        this.thisgame = info;
    }

    private int rowtocoord(int row)
    {
        int coord;

        coord = row * 20 ;
        
        return coord;
    }
    private int coordtorow(int coord)
    {
        int row;

        row = coord /20;
        return row;
    }
    public void sendattack(String attack, int row)
    {
        String user = thisgame.getplayer();
        int level = thisgame.getplayerlevel();
        String reply = "type:gamedata;datatype:attack;user:" + user + ";level:"+level+";word:"+attack+";row:"+row+";";
    }
    public void senddefend(String defend, int xintercept)
    {
        String user = thisgame.getplayer();
        int level = thisgame.getplayerlevel();
        String reply = "type:gamedata;datatype:defend;user:" + user + ";level:"+level+";word:"+defend+";xintercept:"+xintercept+";";
    }
    public void processreceive()
    {
        String received = null;
        getfields(received);
        String player = findinHash("player");
        String word = findinHash("word");
        int level = Integer.parseInt(findinHash("level"));

        boolean myteam = thisgame.inmyteam(player);

        if(findinHash("datatype").equals("attack"))
        {    
            if(myteam)
                addattack(word, false , level ,Integer.parseInt(findinHash("row")));
            else
                addenemyattack(word, Integer.parseInt(findinHash("row")),level);
        }
        else if(findinHash("datatype").equals("defend"))
        {
            if(myteam)
                if(word.equals(enemywords.firstElement().letters)) //if not intercepted
                {
                    prevenemyattack = enemywords.firstElement();
                    enemywords.remove(0);
                    
                }
                else if(word.equals(prevenemyattack.letters) && !enemywords.firstElement().letters.equals(word)) //if already intercepted
                {
                    if(prevenemyattack.interceptedbyme) //check x
                    {
                        int thisx = Integer.parseInt(findinHash("xintercept"));
                        if(thisx < prevenemyattack.getx()) //if someone else has intercepted before i have
                            thisgame.interceptpts(-word.length(), prevenemyattack.getlevel()); //adjust damage
                    }

                }
            else
                checkDefenderWord(word); //just remove

        }
        
    }
    void print(String toprint)
    {
        System.out.println(toprint);
    }
    private boolean getfields(String message)
    {
        print(message);
        String[] msg_array = message.split(";");

        for(String i :msg_array){
            String[] row = i.split(":");
            msg_hashed.put(row[0], row[1]);
        }
        //printhash(msg_hashed);
        System.out.println("testing "+msg_hashed.get("user"));
        return true;

    }
    private String findinHash(String key)
    {
        return (String) msg_hashed.get(key);
    }
}
